<script lang="ts" setup>
import '@wangeditor/editor/dist/css/style.css'
import { inject, ref, reactive, shallowRef, computed, onBeforeUnmount, watch, type PropType } from 'vue'
import type { IEditorConfig } from '@wangeditor/editor'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { defaults } from 'lodash-es'
import { ElMessage } from 'element-plus'

const props = defineProps({
	modelValue: {
		type: String,
		default: '',
	},
	defualtConfig: {
		type: Object as PropType<IEditorConfig>,
	},
	toolbarConfig: {
		type: Object,
	},
	readonly: {
		type: Boolean,
		default: false,
	},
	imageApi: {
		type: Function as PropType<(file: File) => Promise<string>>,
	},
	videoApi: {
		type: Function as PropType<(file: File) => Promise<string>>,
	},
})

const emit = defineEmits(['update:modelValue'])

const injectDefaultImageApi = inject('x-rich-editor:imageApi', undefined)
const injectDefaultVideoApi = inject('x-rich-editor:videoApi', undefined)

const editor = shallowRef()
const content = ref('')

const editorConfig = computed(() =>
	defaults(props.defualtConfig, {
		placeholder: '请输入内容',
		MENU_CONF: {
			/** 上传图片自定义方法 */
			uploadImage: {
				async customUpload(file: File, insertFn: (url: string, alt: string, href: string) => void) {
					const upload = props.imageApi ?? injectDefaultImageApi
					if (!upload) {
						console.error(`[x-rich-editor] not set props.imageApi and inject('x-rich-editor:imageApi')`)
						return
					}
					upload(file)
						.then((url) => {
							insertFn(url, file.name, '')
						})
						.catch((e) => {
							ElMessage.error(e.message)
						})
				},
			},
			uploadVideo: {
				async customUpload(file: File, insertFn: (url: string, alt: string, href: string) => void) {
					const upload = props.videoApi ?? injectDefaultVideoApi
					if (!upload) {
						console.error(`[x-rich-editor] not set props.videoApi and inject('x-rich-editor:videoApi')`)
						return
					}
					upload(file)
						.then((url) => {
							insertFn(url, file.name, '')
						})
						.catch((e) => {
							ElMessage.error(e.message)
						})
				},
			},
		},
	})
)

const toolbarConfig = computed(() =>
	defaults(props.toolbarConfig, {
		excludeKeys: ['fullScreen'],
	})
)

const onCreated = (ed) => {
	editor.value = ed
	toggleEnable(props.readonly)
}

const toggleEnable = (readonly: boolean) => {
	if (!editor.value) return
	if (readonly) {
		editor.value.disable()
	} else {
		editor.value.enable()
	}
}

const getEditor = () => editor.value

watch(
	() => props.modelValue,
	(val) => {
		content.value = val ? val : '<p></p>'
	},
	{ immediate: true }
)
watch(
	() => content.value,
	(val) => {
		emit('update:modelValue', val)
	}
)

watch(
	() => props.readonly,
	(val) => toggleEnable(val)
)

onBeforeUnmount(() => editor?.value?.destroy())

defineExpose({ getEditor })
</script>

<template>
	<div class="x-rich m-2 flex flex-col rounded border shadow">
		<Toolbar class="flex-shrink-0 border-b" :editor="editor" mode="default" :default-config="toolbarConfig" />
		<Editor
			class="flex-grow overflow-y-auto"
			v-model="content"
			:defaultConfig="editorConfig"
			mode="default"
			@onCreated="onCreated"
		/>
	</div>
</template>
